#ifndef DATAMANAGER_H
#define DATAMANAGER_H

#include <QObject>
#include <QJsonObject>
#include <QHash>
#include <QMutex>
#include <QTimer>
#include <QFileSystemWatcher>
#include <memory>
#include "models.h"
#include "../utils/filehandler.h"
#include "../utils/errorhandler.h"

/**
 * @brief 数据管理器
 * 
 * 提供统一的数据访问接口，管理数据缓存，协调文件操作
 * 实现数据的持久化存储和内存缓存的同步
 */

namespace RestaurantSystem {

/**
 * @brief 数据类型枚举
 */
enum class DataType {
    USERS = 0,      // 用户数据
    MENU = 1,       // 菜单数据
    ORDERS = 2,     // 订单数据
    RATINGS = 3,    // 评分数据
    CONFIG = 4      // 配置数据
};

/**
 * @brief 缓存项结构
 */
template<typename T>
struct CacheItem {
    T data;
    QDateTime lastModified;
    bool isDirty; // 是否需要保存到文件
    
    CacheItem() : isDirty(false) {}
    CacheItem(const T& d) : data(d), lastModified(QDateTime::currentDateTime()), isDirty(false) {}
};

/**
 * @brief 数据管理器类
 */
class DataManager : public QObject {
    Q_OBJECT
    
public:
    explicit DataManager(QObject* parent = nullptr);
    ~DataManager();
    
    /**
     * @brief 获取单例实例
     */
    static DataManager& instance();
    
    /**
     * @brief 初始化数据管理器
     * @return 初始化是否成功
     */
    bool initialize();
    
    /**
     * @brief 关闭数据管理器，保存所有缓存数据
     */
    void shutdown();
    
    // ========================================================================
    // 用户数据操作
    // ========================================================================
    
    /**
     * @brief 获取所有顾客
     * @return 顾客列表
     */
    QList<Customer> getAllCustomers();
    
    /**
     * @brief 根据ID获取顾客
     * @param id 顾客ID
     * @return 顾客信息，不存在则返回无效对象
     */
    Customer getCustomerById(const QString& id);
    
    /**
     * @brief 根据用户名获取顾客
     * @param username 用户名
     * @return 顾客信息，不存在则返回无效对象
     */
    Customer getCustomerByUsername(const QString& username);
    
    /**
     * @brief 添加顾客
     * @param customer 顾客信息
     * @return 操作是否成功
     */
    bool addCustomer(const Customer& customer);
    
    /**
     * @brief 更新顾客信息
     * @param customer 顾客信息
     * @return 操作是否成功
     */
    bool updateCustomer(const Customer& customer);
    
    /**
     * @brief 删除顾客
     * @param id 顾客ID
     * @return 操作是否成功
     */
    bool deleteCustomer(const QString& id);
    
    /**
     * @brief 获取管理员配置
     * @return 管理员配置
     */
    AdminConfig getAdminConfig();
    
    /**
     * @brief 更新管理员配置
     * @param config 管理员配置
     * @return 操作是否成功
     */
    bool updateAdminConfig(const AdminConfig& config);
    
    // ========================================================================
    // 菜单数据操作
    // ========================================================================
    
    /**
     * @brief 获取所有菜品
     * @return 菜品列表
     */
    QList<MenuItem> getAllMenuItems();
    
    /**
     * @brief 根据分类获取菜品
     * @param category 分类名称
     * @return 菜品列表
     */
    QList<MenuItem> getMenuItemsByCategory(const QString& category);
    
    /**
     * @brief 根据ID获取菜品
     * @param id 菜品ID
     * @return 菜品信息，不存在则返回无效对象
     */
    MenuItem getMenuItemById(const QString& id);
    
    /**
     * @brief 添加菜品
     * @param item 菜品信息
     * @return 操作是否成功
     */
    bool addMenuItem(const MenuItem& item);
    
    /**
     * @brief 更新菜品信息
     * @param item 菜品信息
     * @return 操作是否成功
     */
    bool updateMenuItem(const MenuItem& item);
    
    /**
     * @brief 删除菜品
     * @param id 菜品ID
     * @return 操作是否成功
     */
    bool deleteMenuItem(const QString& id);
    
    /**
     * @brief 更新菜品库存
     * @param id 菜品ID
     * @param newStock 新库存数量
     * @return 操作是否成功
     */
    bool updateMenuItemStock(const QString& id, int newStock);
    
    /**
     * @brief 获取菜品分类列表
     * @return 分类列表
     */
    QStringList getMenuCategories();
    
    /**
     * @brief 更新菜品分类列表
     * @param categories 新的分类列表
     * @return 操作是否成功
     */
    bool updateMenuCategories(const QStringList& categories);
    
    // ========================================================================
    // 订单数据操作
    // ========================================================================
    
    /**
     * @brief 获取所有订单
     * @return 订单列表
     */
    QList<Order> getAllOrders();
    
    /**
     * @brief 根据顾客ID获取订单
     * @param customerId 顾客ID
     * @return 订单列表
     */
    QList<Order> getOrdersByCustomerId(const QString& customerId);
    
    /**
     * @brief 根据状态获取订单
     * @param status 订单状态
     * @return 订单列表
     */
    QList<Order> getOrdersByStatus(OrderStatus status);
    
    /**
     * @brief 根据ID获取订单
     * @param id 订单ID
     * @return 订单信息，不存在则返回无效对象
     */
    Order getOrderById(const QString& id);
    
    /**
     * @brief 添加订单
     * @param order 订单信息
     * @return 操作是否成功
     */
    bool addOrder(const Order& order);
    
    /**
     * @brief 更新订单信息
     * @param order 订单信息
     * @return 操作是否成功
     */
    bool updateOrder(const Order& order);
    
    /**
     * @brief 删除订单
     * @param id 订单ID
     * @return 操作是否成功
     */
    bool deleteOrder(const QString& id);
    
    // ========================================================================
    // 评分数据操作
    // ========================================================================
    
    /**
     * @brief 获取所有评分
     * @return 评分列表
     */
    QList<Rating> getAllRatings();
    
    /**
     * @brief 根据订单ID获取评分
     * @param orderId 订单ID
     * @return 评分信息，不存在则返回无效对象
     */
    Rating getRatingByOrderId(const QString& orderId);
    
    /**
     * @brief 根据顾客ID获取评分
     * @param customerId 顾客ID
     * @return 评分列表
     */
    QList<Rating> getRatingsByCustomerId(const QString& customerId);
    
    /**
     * @brief 添加评分
     * @param rating 评分信息
     * @return 操作是否成功
     */
    bool addRating(const Rating& rating);
    
    /**
     * @brief 更新评分信息
     * @param rating 评分信息
     * @return 操作是否成功
     */
    bool updateRating(const Rating& rating);
    
    /**
     * @brief 删除评分
     * @param id 评分ID
     * @return 操作是否成功
     */
    bool deleteRating(const QString& id);
    
    // ========================================================================
    // 统计数据操作
    // ========================================================================
    
    /**
     * @brief 生成统计数据
     * @return 统计信息
     */
    Statistics generateStatistics();
    
    /**
     * @brief 获取库存统计
     * @return 库存统计列表
     */
    QList<Statistics::StockInfo> getStockStatistics();
    
    /**
     * @brief 获取销量统计
     * @return 销量统计列表
     */
    QList<Statistics::SalesInfo> getSalesStatistics();
    
    /**
     * @brief 获取评分统计
     * @return 评分统计信息
     */
    Statistics::RatingInfo getRatingStatistics();
    
    // ========================================================================
    // 缓存和数据同步
    // ========================================================================
    
    /**
     * @brief 强制保存所有数据到文件（不创建备份，用于自动保存）
     * @return 操作是否成功
     */
    bool saveAll();
    
    /**
     * @brief 保存所有数据并创建备份（用于重要操作）
     * @return 操作是否成功
     */
    bool saveAllWithBackup();
    
    /**
     * @brief 重新加载所有数据从文件
     * @return 操作是否成功
     */
    bool reloadAll();
    
    /**
     * @brief 清除所有缓存
     */
    void clearCache();
    
    /**
     * @brief 获取缓存统计信息
     * @return 缓存统计字符串
     */
    QString getCacheStats();
    
    /**
     * @brief 设置自动保存间隔
     * @param intervalMs 间隔时间(毫秒)
     */
    void setAutoSaveInterval(int intervalMs);
    
    /**
     * @brief 启用/禁用自动保存
     * @param enabled 是否启用
     */
    void setAutoSaveEnabled(bool enabled);
    
    /**
     * @brief 启用/禁用文件监控
     * @param enabled 是否启用
     */
    void setFileWatchingEnabled(bool enabled);
    
    /**
     * @brief 检查是否为外部文件变更（非本进程引起的变更）
     * @param filePath 文件路径
     * @return 是否为外部变更
     */
    bool isExternalFileChange(const QString& filePath);

signals:
    /**
     * @brief 数据变更信号
     * @param dataType 数据类型
     * @param operation 操作类型
     * @param id 相关ID
     */
    void dataChanged(DataType dataType, const QString& operation, const QString& id);
    
    /**
     * @brief 数据保存完成信号
     * @param dataType 数据类型
     * @param success 是否成功
     */
    void dataSaved(DataType dataType, bool success);
    
    /**
     * @brief 错误发生信号
     * @param errorMessage 错误消息
     */
    void errorOccurred(const QString& errorMessage);
    
    /**
     * @brief 外部文件变更信号
     * @param dataType 数据类型
     * @param filePath 文件路径
     */
    void externalFileChanged(DataType dataType, const QString& filePath);

public slots:
    /**
     * @brief 执行自动保存
     */
    void performAutoSave();
    
    /**
     * @brief 检查文件是否有外部变更（备用机制）
     */
    void checkForExternalChanges();

private slots:
    void onAutoSaveTimer();
    void onFileChanged(const QString& path);

private:
    /**
     * @brief 加载指定类型的数据
     * @param dataType 数据类型
     * @return 操作是否成功
     */
    bool loadData(DataType dataType);
    
    /**
     * @brief 保存指定类型的数据
     * @param dataType 数据类型
     * @param createBackup 是否创建备份文件（默认false，减少不必要的备份）
     * @return 操作是否成功
     */
    bool saveData(DataType dataType, bool createBackup = false);
    
    /**
     * @brief 获取数据文件路径
     * @param dataType 数据类型
     * @return 文件路径
     */
    QString getDataFilePath(DataType dataType);
    
    /**
     * @brief 标记缓存为脏数据
     * @param dataType 数据类型
     */
    void markCacheDirty(DataType dataType);
    
    /**
     * @brief 验证数据完整性
     * @param dataType 数据类型
     * @return 验证结果
     */
    ValidationResult validateData(DataType dataType);
    
    /**
     * @brief 初始化默认数据
     * @param dataType 数据类型
     */
    void initializeDefaultData(DataType dataType);
    
    /**
     * @brief 设置文件监控
     */
    void setupFileWatching();

private:
    static DataManager* s_instance;
    
    std::unique_ptr<FileHandler> m_fileHandler;
    
    // 数据缓存
    CacheItem<QJsonObject> m_usersCache;
    CacheItem<QJsonObject> m_menuCache;
    CacheItem<QJsonObject> m_ordersCache;
    CacheItem<QJsonObject> m_ratingsCache;
    CacheItem<QJsonObject> m_configCache;
    
    // 自动保存
    QTimer* m_autoSaveTimer;
    bool m_autoSaveEnabled;
    int m_autoSaveInterval;
    
    // 文件监控
    QFileSystemWatcher* m_fileWatcher;
    bool m_fileWatchingEnabled;
    QHash<QString, qint64> m_lastModified; // 记录文件最后修改时间，避免重复加载
    
    // 线程安全
    mutable QMutex m_mutex;
    
    // 状态标识
    bool m_isInitialized;
    bool m_isShuttingDown;
    
    // 内部方法（不加锁，用于已经加锁的上下文中）
    Customer getCustomerByUsernameInternal(const QString& username);
    Customer getCustomerByIdInternal(const QString& id);
    bool updateCustomerInternal(const Customer& customer);
};

} // namespace RestaurantSystem

#endif // DATAMANAGER_H
